home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Nebula 2
/
Nebula Two.iso
/
SourceCode
/
Classes
/
HashFile
/
HashFile.m
< prev
next >
Wrap
Text File
|
1995-06-12
|
5KB
|
238 lines
/* File: HashFile.m - db(3) to HashTable bridge
*
* By: Christopher Lane
* Symbolic Systems Resources Group
* Knowledge Systems Laboratory
* Stanford University
*
* Date: 10 September 1991
*
* Copyright: 1990, 1991 by The Leland Stanford Junior University. This
* program may be distributed without restriction for non-commercial use.
*/
#import <c.h>
#import <libc.h>
#import <string.h>
#import <assert.h>
#import "HashFile.h"
#define OBJECT @encode(id)
#define NXRewind(stream) NXSeek(stream, 0L, NX_FROMSTART)
@implementation HashFile
+ (BOOL) isHashFile:(const char *) name
{
return dbExists((char *) name);
}
- initFromFile:(const char *) name
{
return [self initFromFile:name keyDesc:OBJECT valueDesc:OBJECT];
}
- initFromFile:(const char *) name keyDesc:(const char *) aKeyDesc
{
return [self initFromFile:name keyDesc:aKeyDesc valueDesc:OBJECT];
}
- initFromFile:(const char *) name keyDesc:(const char *) aKeyDesc valueDesc:(const char *) aValueDesc
{
NXTypedStream *typedStream;
[self initKeyDesc:aKeyDesc valueDesc:aValueDesc];
if((db = dbOpen(filename = (char *) name)) == NULL) {
[self free];
return nil;
}
readOnly = (BOOL) ((db->flag & (dbFlagReadOnly | dbFlagCompressed)) != 0);
assert(d.k.s = (char *) malloc((size_t) LEAFSIZE));
assert(d.c.s = (char *) malloc((size_t) LEAFSIZE));
d.k.n = malloc_size(d.k.s);
d.c.n = malloc_size(d.c.s);
assert(stream = NXOpenMemory(NULL, 0, NX_READWRITE));
assert(typedStream = NXOpenTypedStream(stream, NX_WRITEONLY));
offset = NXTell(stream);
NXCloseTypedStream(typedStream);
return self;
}
- free
{
free(d.k.s);
free(d.c.s);
NXCloseMemory(stream, NX_FREEBUFFER);
assert(dbClose(db));
return [super free];
}
- empty
{
if(!readOnly && dbClose(db) && dbCreate(filename) && (db = dbInit(filename)) != NULL) return [super empty];
return nil;
}
- (unsigned) count
{
unsigned i = 0;
if(dbFirst(db, &d) && d.k.n > 0) do { ++i; } while(dbNext(db, &d));
assert(i >= count);
return i;
}
- (BOOL) isKey:(const void *) aKey
{
if([super isKey:aKey]) return YES;
[self _keyCvtIn:aKey];
return((BOOL) dbFind(db, &d));
}
- (void *) valueForKey:(const void *) aKey
{
void *value = (void *) nil;
if([super isKey:aKey]) return [super valueForKey:aKey];
[self _keyCvtIn:aKey];
if(dbFetch(db, &d)) [super insertKey:[self _keyCvtOut] value:(value = [self _valueCvtOut])];
return value;
}
- (void *) insertKey:(const void *) aKey value:(void *) aValue
{
if(readOnly) return (void *) nil;
[self _keyCvtIn:aKey];
[self _valueCvtIn:aValue];
if(!dbStore(db, &d)) return (void *) nil;
return [super insertKey:aKey value:aValue];
}
- (void *) removeKey:(const void *) aKey;
{
if(readOnly) return (void *) nil;
[self _keyCvtIn:aKey];
if(!dbDelete(db, &d)) return (void *) nil;
return([super removeKey:aKey]);
}
- (NXHashState) initState
{
NXHashState state = [super initState];
if(state.i = dbFirst(db, &d)) {
state.i = d.k.n;
state.j = d.c.n;
}
return state;
}
- (BOOL) nextState:(NXHashState *) aState key:(const void **) aKey value:(void **) aValue
{
if(aState->i == FALSE) return NO;
d.k.n = aState->i;
d.c.n = aState->j;
if(dbGet(db, &d)) {
*aKey = [self _keyCvtOut];
*aValue = [self _valueCvtOut];
}
else return NO;
if(aState->i = dbNext(db, &d)) {
aState->i = d.k.n;
aState->j = d.c.n;
}
return YES;
}
- (void) _keyCvtIn:(const void *) aKey
{
[self _datumCvtIn:&d.k from:aKey using:keyDesc];
}
- (void) _valueCvtIn:(const void *) aValue
{
[self _datumCvtIn:&d.c from:aValue using:valueDesc];
}
- (void) _datumCvtIn:(Datum *) aDatum from:(const void *) aBuffer using:(const char *) aDesc
{
NXTypedStream *typedStream;
NXRewind(stream);
assert(typedStream = NXOpenTypedStream(stream, NX_WRITEONLY));
offset = NXTell(stream);
NXWriteType(typedStream, aDesc, &aBuffer);
aDatum->n = NXTell(stream) - offset;
NXCloseTypedStream(typedStream);
NXSeek(stream, offset, NX_FROMSTART);
NXRead(stream, (void *) aDatum->s, aDatum->n);
}
- (void *) _keyCvtOut
{
return [self _datumCvtOut:&d.k using:keyDesc];
}
- (void *) _valueCvtOut
{
return [self _datumCvtOut:&d.c using:valueDesc];
}
- (void *) _datumCvtOut:(Datum *) aDatum using:(const char *) aDesc
{
NXTypedStream *typedStream;
void *buffer;
assert(buffer = (void *) malloc((size_t) aDatum->n));
NXSeek(stream, offset, NX_FROMSTART);
NXWrite(stream, (void *) aDatum->s, aDatum->n);
NXRewind(stream);
assert(typedStream = NXOpenTypedStream(stream, NX_READONLY));
NXReadType(typedStream, aDesc, &buffer);
NXCloseTypedStream(typedStream);
return buffer;
}
@end